
# 说明：
# 参数说明：
# folder_a: 文件夹 A 的路径。
# folder_b: 文件夹 B 的路径。
# output_folder: 输出的目标文件夹路径。
# 函数 compute_md5：
# 用于计算文件的 MD5 哈希值，以判断文件内容是否相同。
# 函数 compare_and_copy：
# 使用 os.walk 遍历文件夹 B。
# 对于每个子目录，计算相对于 B 的路径。
# 检查相同路径是否存在于 A 中。
# 如果目录不存在于 A 中，则复制整个目录结构到目标文件夹。
# 如果文件不存在于 A 中，则复制该文件到目标文件夹。
# 如果文件存在，比较文件的 MD5 哈希值，如果不同则复制到目标文件夹。
# 确保目录结构：
# 使用 os.makedirs 确保目标目录结构存在。
# 复制文件：
# 使用 shutil.copy2 复制文件，该方法会保留文件的元数据（如权限、时间戳等）。
# 注意事项：

# 确保你有权限读取和写入指定的文件夹。
# 确保 folder_a 和 folder_b 路径正确无误。
# 如果目标文件夹已经存在，可能会覆盖已有的文件。
# 这个脚本会递归地比较两个文件夹，并将文件夹 B 中与文件夹 A 中不同的文件根据对应的目录结构拷贝到指定的目标文件夹中。希望这个脚本能满足你的需求！如果有任何其他问题，请随时提问。

import os
import shutil
import hashlib

def compute_md5(file_path):
    """计算文件的 MD5 哈希值"""
    hash_md5 = hashlib.md5()
    with open(file_path, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()

def compare_and_copy(src_folder_a, src_folder_b, dest_folder):
    """比较两个文件夹，并将文件夹 B 中与文件夹 A 不同的文件拷贝到目标文件夹"""
    
    # 确保目标文件夹存在
    if not os.path.exists(dest_folder):
        os.makedirs(dest_folder)

    # 遍历文件夹 B
    for root_b, dirs_b, files_b in os.walk(src_folder_b):
        # 计算相对路径
        rel_path = os.path.relpath(root_b, src_folder_b)
        target_root = os.path.join(src_folder_a, rel_path)
        
        # 如果目标根目录不存在，则说明这是文件夹 A 中没有的目录
        if not os.path.exists(target_root):
            # 复制整个目录结构
            new_target_root = os.path.join(dest_folder, rel_path)
            shutil.copytree(root_b, new_target_root)
        else:
            # 遍历文件夹 A 中的文件
            for file_b in files_b:
                src_file_b = os.path.join(root_b, file_b)
                target_file = os.path.join(target_root, file_b)
                
                # 如果文件不存在于文件夹 A 中，则复制到目标文件夹
                if not os.path.exists(target_file):
                    dest_file = os.path.join(dest_folder, rel_path, file_b)
                    dest_dir = os.path.dirname(dest_file)
                    
                    # 确保目标目录存在
                    if not os.path.exists(dest_dir):
                        os.makedirs(dest_dir)
                    
                    shutil.copy2(src_file_b, dest_file)
                else:
                    # 如果文件存在，比较文件的 MD5 哈希值
                    md5_b = compute_md5(src_file_b)
                    md5_a = compute_md5(target_file)
                    
                    if md5_b != md5_a:
                        # 文件内容不同，复制到目标文件夹
                        dest_file = os.path.join(dest_folder, rel_path, file_b)
                        dest_dir = os.path.dirname(dest_file)
                        
                        # 确保目标目录存在
                        if not os.path.exists(dest_dir):
                            os.makedirs(dest_dir)
                        
                        shutil.copy2(src_file_b, dest_file)

if __name__ == "__main__":
    # 指定文件夹路径
    folder_a = '/path/to/folder/A'
    folder_b = '/path/to/folder/B'
    output_folder = '/path/to/output/folder'

    # 调用函数
    compare_and_copy(folder_a, folder_b, output_folder)